home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Tools & Apps / Testing & Debugging / Report Error 1.2 / dialogUtilities.c next >
Encoding:
C/C++ Source or Header  |  1992-01-31  |  20.8 KB  |  815 lines  |  [TEXT/KAHL]

  1. /*================================================================================
  2.     dialogUtilities.c
  3.     
  4.     circa 1991 by Greg Anderson
  5.     greggor@apple.com
  6.     
  7.     FREE DISTRIBUTION--use and enjoy
  8.     
  9.     This file contains various and sundry dialog box utility routines
  10. ================================================================================*/
  11. #include "dialogUtilities.h"
  12.  
  13. #ifndef __TYPES__
  14.     #include <Types.h>
  15. #endif
  16. #ifndef __SYSEQU__
  17.     #include <SysEqu.h>
  18. #endif
  19. #ifndef __ERRORS__
  20.     #include <Errors.h>
  21. #endif
  22. #ifndef __MEMORY__
  23.     #include <Memory.h>
  24. #endif
  25. #ifndef __RESOURCES__
  26.     #include <Resources.h>
  27. #endif
  28.  
  29. #ifndef __QUICKDRAW__
  30.     #include <Quickdraw.h>
  31. #endif
  32. #ifndef __CONTROLS__
  33.     #include <Controls.h>
  34. #endif
  35. #ifndef __DIALOGS__
  36.     #include <Dialogs.h>
  37. #endif
  38. #ifndef __TOOLUTILS__
  39.     #include <ToolUtils.h>
  40. #endif
  41. #ifndef __SCRAP__
  42.     #include <Scrap.h>
  43. #endif
  44.  
  45. /*----------------------------------------------------------------------
  46.     MessageBox
  47.     
  48.     Display a message
  49. ----------------------------------------------------------------------*/
  50. void MessageBox( Str255 pstr )
  51. {
  52.     DialogPtr        dlog;
  53.     short            itemHit;
  54.  
  55.     dlog = GetNewDialog( 150, (Ptr)0L, (WindowPtr)-1L);
  56.  
  57.     if( dlog != nil )
  58.     {
  59.         SetPort( dlog );
  60.         ParamText( pstr, nil, nil, nil );
  61.         SelectWindow(dlog);
  62.         InstallDefaultOutline( dlog, 1 );
  63.         CenterAndShowDialog(dlog);
  64.         /*
  65.         // Wait for user to click "Okay"
  66.         */
  67.         do
  68.         {
  69.             ModalDialog((ModalFilterProcPtr) CutPasteFilter, &itemHit);
  70.         } while( itemHit != 1 );
  71.         DisposDialog(dlog);
  72.     }
  73.     else
  74.     {
  75.         DebugStr( pstr );
  76.     }
  77. }
  78.  
  79. /*----------------------------------------------------------------------
  80.     CenterAndShowDialog
  81.     
  82.     Center the specified dialog box & show it
  83.     
  84.     This code centers the dialog box on the main monitor (the one
  85.     with the menu bar) such that 1/3rd of the empty space left on
  86.     that screen is above the dialog and 2/3rds of it is below the
  87.     dialog
  88.  
  89.     Note:
  90.     
  91.     This routine looks at MBarHeight to correctly calculate the
  92.     horizontal position of the dialog box.  Accessing low memory
  93.     globals is generally an evil thing to do, but in this case
  94.     there is no good alternative.
  95. ----------------------------------------------------------------------*/
  96. void CenterAndShowDialog(DialogPtr dlog)
  97. {
  98.     short            menuHeight;
  99.     short            dlogWidth;
  100.     short            dlogHeight;
  101.     short            scrnWidth;
  102.     short            scrnHeight;
  103.     short            newDlogX;
  104.     short            newDlogY;
  105.     
  106.     /*
  107.     // Look at the low memory global 'MBarHeight' to determine the
  108.     // height of the menu bar (in pixels)
  109.     #ifdef THINK_C
  110.         menuHeight = MBarHeight;
  111.     #else
  112.     */
  113.     menuHeight = *((short*)MBarHeight);
  114.     /*
  115.     // Calculate the size of the dialog box and the main screen
  116.     // (without the menu bar)
  117.     */
  118.     dlogWidth    = (dlog->portRect.right - dlog->portRect.left);
  119.     dlogHeight    = (dlog->portRect.bottom - dlog->portRect.top);
  120.     scrnWidth    = (qd.screenBits.bounds.right - qd.screenBits.bounds.left);
  121.     scrnHeight    = (qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - menuHeight;
  122.     /*
  123.     // Quick check: don't leave any empty space if the dialog is
  124.     // too large to fit on the main screen.  This sanity check
  125.     // really should not be necessary, though, as all dialog boxes
  126.     // should fit on 9" screens
  127.     */
  128.     if( dlogHeight > scrnHeight)
  129.         dlogHeight = scrnHeight;
  130.     /*
  131.     // Calculate the menu's new location
  132.     */
  133.     newDlogX = qd.screenBits.bounds.left + (scrnWidth - dlogWidth) / 2;
  134.     newDlogY = qd.screenBits.bounds.top + menuHeight + (scrnHeight - dlogHeight) / 3;
  135.     /*
  136.     // Move the dialog and show it
  137.     */
  138.     MoveWindow(dlog,newDlogX,newDlogY,false);
  139.     ShowWindow(dlog);
  140. }
  141.  
  142. /*----------------------------------------------------------------------
  143.     AddNewUserItem
  144.     
  145.     Creates a new useritem in the specified dialog box & returns
  146.     its item number
  147. ----------------------------------------------------------------------*/
  148. short AddNewUserItem( DialogPtr dlog )
  149. {
  150.     DialogPeek        theDialog        = (DialogPeek)dlog;
  151.     short**            itemHandle        = (short**)theDialog->items;
  152.     short            nItems            = **itemHandle + 1;
  153.     short            newItem            = 0;
  154.     DITLitem*        ditlPtr;
  155.     Size            itemHandleSize;
  156.     
  157.     itemHandleSize = GetHandleSize( (Handle)itemHandle );
  158.     SetHandleSize( (Handle)itemHandle, itemHandleSize + sizeof(DITLitem) );
  159.     if( MemError() == noErr )
  160.     {
  161.         /*
  162.         // We dereference the (potentially) unlocked itemHandle
  163.         // here; don't do any memory-moving calls until we've
  164.         // initialized the new DITL item
  165.         */
  166.         ditlPtr = (DITLitem*) ( (*itemHandle) + (itemHandleSize / sizeof(short)) );
  167.         /*
  168.         // Fill in the new fields
  169.         */
  170.         ditlPtr->placeholder = 0;
  171.         ditlPtr->itemType = userItem;
  172.         ditlPtr->extraLength = 0;
  173.         /*
  174.         // Remember / record the new number of items
  175.         */
  176.         newItem = nItems + 1;
  177.         **itemHandle = newItem - 1;
  178.     }
  179.     
  180.     return newItem;
  181. }
  182.  
  183. /*----------------------------------------------------------------------
  184.     DrawDottedLineProc
  185.     
  186.     Draw a dotted line
  187. ----------------------------------------------------------------------*/
  188. pascal void DrawDottedLineProc(DialogPtr dlog, short item)
  189. {
  190.     short                type;
  191.     Handle                itemHandle;
  192.     Rect                box;
  193.     PenState            saveState;
  194.     Point                lineStart;
  195.     Point                lineEnd;
  196.     
  197.     /*
  198.     // Save the drawing mode before doing anything with
  199.     // the pen
  200.     */
  201.     GetPenState( &saveState );
  202.     /*
  203.     // Get the bounding box of the userItem & set lineStart
  204.     // to the upper left corner and lineEnd to the lower right
  205.     // corner of the bounding rectangle
  206.     */
  207.     GetDItem(dlog, item, &type, (Handle*)&itemHandle, &box);
  208.     lineStart.h = box.left;
  209.     lineStart.v = box.top;
  210.     lineEnd.h = box.right;
  211.     lineEnd.v = box.bottom;
  212.     /*
  213.     // The line is always drawn along the longer edge
  214.     */
  215.     if( (lineEnd.h - lineStart.h) > (lineEnd.v - lineStart.v) )
  216.         lineEnd.v = lineStart.v;
  217.     else
  218.         lineEnd.h = lineStart.h;
  219.     /*
  220.     // Set the pen mode and draw the line
  221.     */
  222.     PenNormal();
  223.     PenPat(qd.gray);
  224.     MoveTo( lineStart.h, lineStart.v );
  225.     LineTo( lineEnd.h, lineEnd.v );
  226.     /*
  227.     // Restore the pen state
  228.     */
  229.     SetPenState( &saveState );
  230. }
  231.  
  232. /*----------------------------------------------------------------------
  233.     SetUserItemToDottedLine
  234.     
  235.     Make the given userItem a dotted line
  236. ----------------------------------------------------------------------*/
  237. void SetUserItemToDottedLine( DialogPtr dlog, short whichItem )
  238. {
  239.     short            type;
  240.     Handle            itemHandle;
  241.     Rect            box;
  242.     
  243.     GetDItem(dlog,whichItem,&type,&itemHandle,&box);
  244.     SetDItem(dlog,whichItem,type,(Handle)DrawDottedLineProc,&box);
  245. }
  246.  
  247. /*----------------------------------------------------------------------
  248.     DrawFrameRectProc
  249.     
  250.     Draw a frame around the specified userItem
  251. ----------------------------------------------------------------------*/
  252. pascal void DrawFrameRectProc(DialogPtr dlog, short item)
  253. {
  254.     short                type;
  255.     Handle                itemHandle;
  256.     Rect                box;
  257.     PenState            saveState;
  258.     
  259.     /*
  260.     // Save the drawing mode before doing anything with
  261.     // the pen
  262.     */
  263.     GetPenState( &saveState );
  264.     /*
  265.     // Get the bounding box of the userItem
  266.     */
  267.     GetDItem(dlog, item, &type, (Handle*)&itemHandle, &box);
  268.     /*
  269.     // Set the pen mode and draw the box
  270.     */
  271.     PenNormal();
  272.     FrameRect( &box );
  273.     /*
  274.     // Restore the pen state
  275.     */
  276.     SetPenState( &saveState );
  277. }
  278.  
  279. /*----------------------------------------------------------------------
  280.     SetUserItemToFrameRect
  281.     
  282.     Make the given userItem a dotted line
  283. ----------------------------------------------------------------------*/
  284. void SetUserItemToFrameRect( DialogPtr dlog, short whichItem )
  285. {
  286.     short            type;
  287.     Handle            itemHandle;
  288.     Rect            box;
  289.     
  290.     GetDItem(dlog,whichItem,&type,&itemHandle,&box);
  291.     SetDItem(dlog,whichItem,type,(Handle)DrawFrameRectProc,&box);
  292. }
  293.  
  294. /*----------------------------------------------------------------------
  295.     DrawDefaultProc
  296.     
  297.     Draw the thick rounded rectangle around the default button
  298.  
  299.     This routine uses Keith Rollin's algorithm, as presented in the
  300.     USENET Guide to Programming the Macintosh.  I have modified the
  301.     basic algorithm only slightly--I add two to the calculated
  302.     'buttonOval' value.  This gets better results, particularly for
  303.     buttons of the default size (18 points).
  304.     
  305.     The only reason this procedure takes a second parameter is so
  306.     that it may be installed as a UserItem procedure if desired.
  307.     The recommended way to use this procedure is in conjunction
  308.     with the CutPasteFilter.
  309. ----------------------------------------------------------------------*/
  310. pascal void DrawDefaultProc(DialogPtr dlog, short item)
  311. {
  312.     short                defaultButton;
  313.     
  314.     /*
  315.     // Don't call GetDItem if the default button # has a strange value
  316.     */
  317.     defaultButton = ((DialogPeek)dlog)->aDefItem;
  318.     if( defaultButton > 0 )
  319.     {
  320.         short                type;
  321.         Handle                userHandle;
  322.         Rect                outlineBox;
  323.  
  324.         /*
  325.         // Only draw the bold outline around the default button
  326.         // if it really is a button
  327.         */
  328.         GetDItem(dlog, defaultButton, &type, &userHandle, &outlineBox);
  329.         if( (type & ~itemDisable) == ctrlItem + btnCtrl )
  330.         {
  331.             PenState            saveState;
  332.             short                buttonOval;
  333.  
  334.             GetPenState( &saveState );
  335.             InsetRect(&outlineBox,-4,-4);
  336.             /*
  337.             // We want to draw the thick line with a normal
  338.             // pen pattern that is 3 pixels wide
  339.             */
  340.             PenNormal();
  341.             PenSize(3,3);
  342.             /*
  343.             // If the button we are outlining is disabled,
  344.             // draw the outline with a gray pattern.
  345.             */
  346.             if( !ButtonEnabled(dlog, defaultButton ) )
  347.             {
  348.                 PenPat(qd.gray);
  349.             }
  350.             /*
  351.             // Calculate the curvature to use and draw the thick line
  352.             */
  353.             buttonOval = 2 + (outlineBox.bottom - outlineBox.top) / 2;
  354.             FrameRoundRect(&outlineBox,buttonOval,buttonOval);
  355.             
  356.             SetPenState( &saveState );
  357.         }
  358.     }
  359. }
  360.  
  361. /*----------------------------------------------------------------------
  362.     This function creates a useritem around the default button &
  363.     installs a drawing proc that draws the default border around it.
  364.     
  365.     If you want a button other than button #1 to act as the default
  366.     button, don't forget to supply your own filterProc that
  367.     translates Return to the correct item number.  If you use the
  368.     CutPasteFilter implemented in this file, Return and Enter will
  369.     be translated to be equivalent to clicking on the button that
  370.     has the default outline around it.
  371. ----------------------------------------------------------------------*/
  372. short InstallDefaultOutline(DialogPtr dlog, short button)
  373. {
  374.     ((DialogPeek)dlog)->aDefItem = button;
  375.     
  376.     return button;
  377. }
  378.  
  379. /*----------------------------------------------------------------------
  380.     Draw the thick square rectangle around the dialog item that accepts
  381.     keyboard input (see the System 7 Chooser for an example).
  382. ----------------------------------------------------------------------*/
  383. pascal void DrawActiveItemProc(DialogPtr dlog, short item)
  384. {
  385.     short            type;
  386.     Handle            itemHandle;
  387.     Rect            box;
  388.     PenState        saveState;
  389.     
  390.     GetPenState( &saveState );
  391.     GetDItem(dlog, item, &type, &itemHandle, &box);
  392.     PenNormal();
  393.     PenSize(2,2);
  394.     FrameRect(&box);
  395.     SetPenState( &saveState );
  396. }
  397.  
  398. /*----------------------------------------------------------------------
  399.     This function creates a useritem around the specified button & installs
  400.     a drawing proc that draws the default border around it.
  401. ----------------------------------------------------------------------*/
  402. short InstallActiveItemOutline(DialogPtr dlog, short button)
  403. {
  404.     short            userItem;
  405.     short            type;
  406.     Handle            item;
  407.     Rect            box;
  408.     Rect            userBox;
  409.     
  410.     userItem = AddNewUserItem( dlog );
  411.     if( userItem > 0 )
  412.     {
  413.         GetDItem(dlog, button, &type, &item, &box);
  414.         InsetRect(&box,-4,-4);
  415.         GetDItem(dlog, userItem, &type, &item, &userBox);
  416.         SetDItem(dlog, userItem, type, (Handle)DrawActiveItemProc, &box );
  417.     }
  418.     
  419.     return userItem;
  420. }
  421.  
  422. /*----------------------------------------------------------------------
  423.     MoveOutline
  424.     
  425.     Move a userItem around the appropriate button.
  426.     
  427.     This function should be used in conjunction with
  428.     InstallDefaultOutline to move the default button indicator
  429.     from one button to another.  If you are using the
  430.     CutPasteFilter with this routine, Return and Enter will
  431.     automatically be translated to the correct button
  432. ----------------------------------------------------------------------*/
  433. void MoveOutline(DialogPtr dlog, short userItem, short button)
  434. {
  435.     short            type;
  436.     Handle            item;
  437.     Rect            newBox;
  438.     Rect            oldBox;
  439.     
  440.     GetDItem(dlog, ((DialogPeek)dlog)->aDefItem, &type, &item, &oldBox);
  441.     InsetRect(&oldBox,-4,-4);
  442.     GetDItem(dlog, button, &type, &item, &newBox);
  443.     InsetRect(&newBox,-4,-4);
  444.     /*
  445.     // Erase the old box & invalidate the old and new
  446.     // locations to force a redraw
  447.     */
  448.     EraseRect( &oldBox );
  449.     InvalRect( &oldBox );
  450.     InvalRect( &newBox );
  451.     /*
  452.     // Remember where the default button outline moved to
  453.     */
  454.     ((DialogPeek)dlog)->aDefItem = button;
  455. }
  456.  
  457. /*----------------------------------------------------------------------
  458.     MoveActiveIndicator
  459.     
  460.     Move the active item indicator to another item.
  461.     
  462.     Note:    This routine erases and redraws the active item.
  463.             It would be better to erase & invalidate, but that's
  464.             pretty slow.
  465. ----------------------------------------------------------------------*/
  466. void MoveActiveIndicator(DialogPtr dlog, short userItem, short button)
  467. {
  468.     short            type;
  469.     Handle            item;
  470.     Rect            box;
  471.     Rect            userBox;
  472.     RgnHandle        badRgn;
  473.     RgnHandle        tmpRgn;
  474.     
  475.     GetDItem(dlog, button, &type, &item, &box);
  476.     InsetRect(&box,-4,-4);
  477.     GetDItem(dlog, userItem, &type, &item, &userBox);
  478.     SetDItem(dlog, userItem, type, item, &box );
  479.     /*
  480.     // Erase the old active item indicator
  481.     */
  482.     badRgn = NewRgn();
  483.     tmpRgn = NewRgn();
  484.     RectRgn( badRgn, &userBox );
  485.     InsetRect( &userBox, 2, 2 );
  486.     RectRgn( tmpRgn, &userBox );
  487.     DiffRgn( badRgn, tmpRgn, badRgn );
  488.     EraseRgn( badRgn );
  489.     InvalRgn( badRgn );
  490.     DisposeRgn( badRgn );
  491.     DisposeRgn( tmpRgn );
  492.     /*
  493.     // Draw the new one
  494.     */
  495.     DrawActiveItemProc( dlog, userItem );
  496. }
  497.  
  498. /*----------------------------------------------------------------------
  499.     MoveDItem
  500.     
  501.     Move a Dialog Item.
  502.     
  503.     This is not _quite_ as easy as it sounds, because if the item
  504.     is a control (such as a check box or radio button), MoveControl
  505.     must also be called.
  506.     
  507.     NOTE:    This routine doesn't quite work, because it does not
  508.             erase or redraw the item that moved unless it is
  509.             a control.  Tsk tsk.
  510. ----------------------------------------------------------------------*/
  511. void MoveDItem( DialogPtr dlog, short itemNumber, short h, short v )
  512. {
  513.     Handle            itemHandle;
  514.     short            itemType;
  515.     Rect            box;
  516.     
  517.     /*
  518.     // Get some useful information about the DItem to move
  519.     */
  520.     GetDItem( dlog, itemNumber, &itemType, (Handle*)&itemHandle, &box );
  521.     /*
  522.     // Move the bounding box to the correct location
  523.     */
  524.     box.bottom += (v - box.top);
  525.     box.right += (h - box.left);
  526.     box.top = v;
  527.     box.left = h;
  528.     /*
  529.     // Set the bounding box of the item to move
  530.     */
  531.     SetDItem( dlog, itemNumber, itemType, (Handle)itemHandle, &box );
  532.     /*
  533.     // If the item is a control, call MoveControl
  534.     */
  535.     if( (itemType & ctrlItem) != 0 )
  536.     {
  537.         MoveControl( (ControlHandle)itemHandle, h, v );
  538.     }
  539. }
  540.  
  541. /*----------------------------------------------------------------------
  542.     SetItemHandle
  543.     
  544.     Set the item handle of a dialog item (particularly useful for
  545.     useritems)
  546. ----------------------------------------------------------------------*/
  547. void SetItemHandle( DialogPtr dlog, short whichItem, Handle newItem )
  548. {
  549.     short            type;
  550.     Handle            itemHandle;
  551.     Rect            box;
  552.     
  553.     GetDItem(dlog,whichItem,&type,&itemHandle,&box);
  554.     SetDItem(dlog,whichItem,type,newItem,&box);
  555. }
  556.  
  557. /*----------------------------------------------------------------------
  558.     GetItemPoint
  559.     
  560.     Returns the location of a given dialog item
  561. ----------------------------------------------------------------------*/
  562. Point GetItemPoint( DialogPtr dlog, short itemNum )
  563. {
  564.     Point        loc;
  565.     short        type;
  566.     Handle        item;
  567.     Rect        box;
  568.     
  569.     GetDItem(dlog,itemNum, &type, &item, &box);
  570.     loc.h = box.left;
  571.     loc.v = box.top;
  572.     return( loc );
  573. }
  574.  
  575. /*----------------------------------------------------------------------
  576.     ButtonEnabled
  577.     
  578.     This routine is used by DrawDefaultProc and CutPasteFilter
  579.     to determine if the default button is enabled
  580. ----------------------------------------------------------------------*/
  581. Boolean ButtonEnabled(DialogPtr dlog, short item)
  582. {
  583.     ControlHandle        buttonHandle = nil;
  584.     Rect                buttonBox;
  585.     short                type;
  586.  
  587.     GetDItem(dlog, item, &type, (Handle*)&buttonHandle, &buttonBox);
  588.     if( (buttonHandle == nil) || ((type & ctrlItem) == 0) )
  589.         return false;
  590.     
  591.     /*
  592.     // A contrlHilite value of 255 indicates that the button
  593.     // is disabled
  594.     */
  595.     return ( (*buttonHandle)->contrlHilite != 255 );
  596. }
  597.  
  598. /*----------------------------------------------------------------------
  599.     EnableButton
  600.     
  601.     This simple routine will enable or disable a button
  602. ----------------------------------------------------------------------*/
  603. pascal void EnableButton(DialogPtr dlog, short button,Boolean enable)
  604. {
  605.     ControlHandle        buttonHandle;
  606.     short                type;
  607.     Rect                box;
  608.     
  609.     GetDItem(dlog,button,&type,(Handle*)&buttonHandle,&box);
  610.     HiliteControl(buttonHandle, enable ? 0 : 255);
  611. }
  612.  
  613. /*----------------------------------------------------------------------
  614.     FlashDlogItem
  615.     
  616.     Momentarily hilite a dialog button
  617. ----------------------------------------------------------------------*/
  618. void FlashDlogItem( DialogPtr dlog, short itemNum )
  619. {
  620.     ControlHandle        itemHandle;
  621.     short                itemType;
  622.     Rect                iRect;
  623.     
  624.     GetDItem(dlog,itemNum,&itemType,(Handle*)&itemHandle,&iRect);
  625.     if( itemType == ctrlItem + btnCtrl )
  626.     {
  627.         long            ticky;
  628.  
  629.         HiliteControl(itemHandle,1);
  630.         Draw1Control(itemHandle);
  631.         ticky = TickCount() + 10;
  632.         while( ticky > TickCount() );
  633.         HiliteControl(itemHandle,0);
  634.         Draw1Control(itemHandle);
  635.     }
  636. }
  637.  
  638. /*----------------------------------------------------------------------
  639.     CutPasteFilter
  640.     
  641.     This filter, when passed to ModalDialog, will allow the user to
  642.     cut, copy and paste by pressing command-X, command-C or command-V,
  643.     respectively.  It also checks if the cursor is over an editText
  644.     item, and if so, the cursor is changed into an IBeam.
  645.     
  646.     This procedure may be used as the filterProc of any dialog that
  647.     uses ModelDialog().  Note that this filter calls FlashDlogItem(),
  648.     above.  In all other respects, it is completely self-contained.
  649.     
  650.     This routine always translates command-. to button #2.
  651.     Your dialog box should have button #2 set up as a
  652.     'Cancel' button if you use this routine.
  653. ----------------------------------------------------------------------*/
  654. pascal Boolean CutPasteFilter( DialogPtr dlog, EventRecord* event, short* item )
  655. {
  656.     DialogRecord    *dp = (DialogRecord *)dlog;
  657.     TEHandle        te;
  658.     Str255            Pstr;
  659.     long            num;
  660.     char            key;
  661.     char            code;
  662.     short            itemType = statText;
  663.     short            itemNum;
  664.     Handle            itemHandle;
  665.     Point            mouse;
  666.     Rect            tRect;
  667.     
  668.     te = dp->textH;
  669.     /*
  670.     // Adjust the cursor to an iBeam or Arrow as appropriate
  671.     */    
  672.     GetMouse( &mouse );
  673.     itemNum = FindDItem(dlog,mouse) + 1;
  674.     if( itemNum > 0 )
  675.         GetDItem(dlog,itemNum,&itemType,&itemHandle,&tRect);
  676.     SetCursor( (itemType == editText) ? *GetCursor(iBeamCursor) : &qd.arrow);
  677.     
  678.     /*
  679.     // If the event is an update event, check to see
  680.     // if it is for this dialog or for some other window
  681.     */
  682.     if( (event->what == updateEvt) )
  683.     {
  684.         /*
  685.         // If the update event is for this dialog box,
  686.         // then draw the default button
  687.         */
  688.         if( StripAddress((DialogPtr)event->message) == StripAddress(dlog) )
  689.         {
  690.             /*
  691.             // The 'item' parameter is ignored, but we
  692.             // don't have any better value to pass to
  693.             // it than the item # of the default button
  694.             */
  695.             DrawDefaultProc(dlog, ((DialogPeek)dlog)->aDefItem );
  696.         }
  697.         else
  698.         {
  699.             /*
  700.             // At this point your application should
  701.             // call "UpdateEvent( event->message )"
  702.             // (or "UpdateEvent( event )", if you prefer),
  703.             // where "UpdateEvent" is the procedure that
  704.             // you call from your main event loop when
  705.             // you receive an update event.
  706.             */
  707.         }
  708.     }
  709.     
  710.     /*
  711.     // Is the event a key-down event?
  712.     */
  713.     if( (event->what == keyDown) || (event->what == autoKey) )
  714.     {
  715.         key  = (event->message & charCodeMask);
  716.         code = (event->message &  keyCodeMask) >> 8;
  717.         /*
  718.         // If F2, F3 or F4 (cut, copy or paste) are pressed,
  719.         // forge a Command-X, C or V and handle the appropriate
  720.         // command below.
  721.         */
  722.         switch( code )
  723.         {
  724.             case 120:
  725.             {
  726.                 event->modifiers |= cmdKey;
  727.                 key = 'x';
  728.                 break;
  729.             }
  730.             
  731.             case  99:
  732.             {
  733.                 event->modifiers |= cmdKey;
  734.                 key = 'c';
  735.                 break;
  736.             }
  737.             
  738.             case 118:
  739.             {
  740.                 event->modifiers |= cmdKey;
  741.                 key = 'v';
  742.                 break;
  743.             }
  744.         }
  745.         /*
  746.         // Is the command key down?
  747.         */
  748.         if( event->modifiers & cmdKey )
  749.         {
  750.             switch( key )
  751.             {
  752.                 /*
  753.                 // Command-X, C and V are cut, copy and paste.
  754.                 */
  755.                 case 'x':
  756.                 case 'c':
  757.                 {
  758.                     ZeroScrap();
  759.                     if( key == 'x' )
  760.                         DlgCut( dlog );
  761.                     else
  762.                         DlgCopy( dlog );
  763.                     if( TEToScrap() != noErr )
  764.                         SysBeep(120);
  765.                     return true;
  766.                 }
  767.                                         
  768.                 case 'v':
  769.                 {
  770.                     if( TEFromScrap() == noErr )
  771.                         DlgPaste( dlog );
  772.                     else
  773.                         SysBeep(120);
  774.                     return true;
  775.                 }
  776.                 
  777.                 /*
  778.                 // Command-. cancels
  779.                 */
  780.                 case '.':
  781.                 {
  782.                     *item = 2;
  783.                     FlashDlogItem( dlog, *item );
  784.                     return true;
  785.                 }
  786.             }
  787.             /*
  788.             // All other command-key combinations do nothing
  789.             */
  790.             event->what = nullEvent;
  791.             return false;
  792.         }
  793.         /*
  794.         // If RETURN or ENTER was pressed, exit with
  795.         // itemHit = ((DialogPeek)dlog)->aDefItem--but only if the
  796.         // default button is enabled.
  797.         */
  798.         if( ((key == 13) || (key == 3)) && ButtonEnabled(dlog,((DialogPeek)dlog)->aDefItem) )
  799.         {
  800.             *item = ((DialogPeek)dlog)->aDefItem;
  801.             FlashDlogItem( dlog, *item );
  802.             return true;
  803.         }
  804.         /*
  805.         // Swallow non-printing characters
  806.         */
  807.         if( (key < ' ') && (key != 8) && (key != 9) )
  808.         {
  809.             event->what = nullEvent;
  810.             return false;
  811.         }
  812.     }
  813.     return false;
  814. }
  815.